package com.wisdom.system.api.core.aop;

import com.alibaba.fastjson.JSON;
import com.wisdom.system.entity.sys.SysSystemLog;
import com.wisdom.system.service.sys.SysSystemLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @Description:获取请求的入参和出参
 */
@Component
@Aspect
public class RequestAspect {

    @Autowired
    private SysSystemLogService sysSystemLogService;

    private static final Logger logger = LoggerFactory.getLogger(RequestAspect.class);

    @Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)")
    public void pointcut() {}


    @Around("pointcut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //IP地址
        String ipAddr = getRemoteHost(request);
        String url = request.getRequestURL().toString();
        String reqParam = preHandle(joinPoint,request);
        //获得第一个/的位置
        int index = url.indexOf("/");
        //根据第一个/的位置 获得第3个点的位置
        index = url.indexOf("/", index+3);
        //根据第三个/的位置，截取字符串。得到结果
        url = url.substring(index);
        //请求参数
        save(ipAddr,url,"{" + reqParam + "}","01","请求参数");
        Object result = joinPoint.proceed();
        String respParam = postHandle(result);
        //返回参数
        save(ipAddr,url,"{" + reqParam + "}","02","返回参数");
        return result;
    }

    /**
     * 入参数据
     *
     * @param joinPoint
     * @param request
     * @return
     */
    private String preHandle(ProceedingJoinPoint joinPoint,HttpServletRequest request) {
        String reqParam = "";
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        Annotation[] annotations = targetMethod.getAnnotations();
        for (Annotation annotation : annotations) {
            //此处可以改成自定义的注解
            if (annotation.annotationType().equals(RequestMapping.class)) {
                reqParam = JSON.toJSONString(request.getParameterMap());
                break;
            }
        }
        return reqParam;
    }

    /**
     * 返回数据
     *
     * @param retVal
     * @return
     */
    private String postHandle(Object retVal) {
        if(null == retVal){
            return "";
        }
        return JSON.toJSONString(retVal);
    }


    /**
     * 获取目标主机的ip
     *
     * @param request
     * @return
     */
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    /**
     * 封装日志方法
     *
     * @param ipAddress
     * @param requestRout
     * @param requestParam
     * @param requestTypeCode
     * @param requestTypeName
     * @return
     */
    private SysSystemLog save(String ipAddress,String requestRout,String requestParam,String requestTypeCode,String requestTypeName){
        SysSystemLog sysSystemLog = new SysSystemLog();
        sysSystemLog.setAddTime(new Date());
        sysSystemLog.setIpAddress(ipAddress);
        sysSystemLog.setParam(requestParam);
        sysSystemLog.setRequestRouting(requestRout);
        sysSystemLog.setRequestTypeCode(requestTypeCode);
        sysSystemLog.setRequestTypeName(requestTypeName);
        sysSystemLogService.addSysSystemLogInfo(sysSystemLog);
        return sysSystemLog;
    }
}
